import sys,pprint,copy,pattern,frequency,substitution,os,presolve

from detectEnglish import isEnglish
from pattern import LETTERS

def hack(message=''):

    
    # Determine the possible valid ciphertext translations.
    print('Hacking...')
    solvedmessage = presolve.solve(message)
    letterMapping = pattern.getLetterMapping_byPatterns(solvedmessage)
    
    print 'walking keys space mapping:'
    pprint.pprint(letterMapping)
    
    # Display the results to the user.
    return walk_keyspace_withmapping(message,letterMapping)

RESULTLIMIT = 10
resultcount = 0
FilTEDPERCENTAGE = 80
EXCELLENTPERCENTAGE = 95
STOPSEARCHING = False
def walk_keyspace_withmapping(message, letterMapping):
    
    mappedLetters = []
    unsolvedLetters = []
    
    def addingLetter_tokey(key,letter,cipherletter):
        
        key = copy.deepcopy(key)
        keyIndex = LETTERS.find(letter)
        key[keyIndex] = cipherletter
        return key
    
    def stopsearch_y_or_n():
        stop = raw_input('stop searching?(y/n)')
        if stop == 'y' :
            global STOPSEARCHING
            STOPSEARCHING = True
    
    
    initialkey = ['x']*len(LETTERS)
    for cipherletter in LETTERS:
        if len(letterMapping[cipherletter]) == 1:
            mappedLetters.append(letterMapping[cipherletter][0])
            initialkey = addingLetter_tokey(initialkey, letterMapping[cipherletter][0], cipherletter)
        if len(letterMapping[cipherletter]) > 1:
            unsolvedLetters.append(cipherletter)

    properHacked = {}
    
    def dfs(unsolvedlist,mappedlist,currentkey):
        
        global resultcount
        global STOPSEARCHING
        if STOPSEARCHING:
            return
        if len(unsolvedlist) == 0:
            currentkey = ''.join(currentkey)
            decry = substitution.translateMessage(message, currentkey, 'D')
            if isEnglish(decry,FilTEDPERCENTAGE):
                print 'GOODKEY ',resultcount+1,' :'+currentkey
                if isEnglish(decry,EXCELLENTPERCENTAGE):
                    print 'EXCELLENT GOODKEY!,result plain text is: '
                    print decry
                    decry = 'EXCELLENT GOODKEY!\n'+decry
                    #stopsearch_y_or_n()
                properHacked[currentkey] = decry
                resultcount += 1
            return
        
        if resultcount >= RESULTLIMIT:
            return
        
        
        unsolvedlist = copy.deepcopy(unsolvedlist)
        mappedlist = copy.deepcopy(mappedlist)
        
        cipherletter = unsolvedlist.pop()
        for mappingletter in letterMapping[cipherletter]:
            if mappingletter not in mappedlist:
                mappedlist.append(mappingletter)
                nextkey = addingLetter_tokey(currentkey, mappingletter, cipherletter)
                dfs(unsolvedlist,mappedlist,nextkey)
                mappedlist.remove(mappingletter)

    global resultcount
    global STOPSEARCHING
    resultcount = 0
    STOPSEARCHING = False
    dfs(unsolvedLetters,mappedLetters,initialkey)
    return properHacked

def main():
    path_doc = raw_input('the path of ciphertext: ')
    hacked = {}
    if os.path.isfile(path_doc):
        hacked = hack(open(path_doc,'r').read())
    for key in hacked:
        outfilename = r'hacked/hacked.'+os.path.basename(path_doc)+'.'+key
        fout = open(outfilename,'w')
        fout.write('KEY:\n'+key+'\n')
        fout.write(hacked[key])
        fout.close()
    print 'ALL GOOD RESULT WRITEN to file\n'
     
if __name__ == '__main__':
    main()
    #pprint.pprint(hack(open('sources/changyidian','r').read()))
